package repository

import (
	"errors"
	"gorm.io/gorm"

	"go_user_manager/internal/adapters/database"
	"go_user_manager/internal/domain"
	"go_user_manager/pkg/framework"
)

type UserRepo struct {
	logger framework.Logger
	db     *gorm.DB
}

func NewUserRepo(logger framework.Logger, db *gorm.DB) *UserRepo {
	return &UserRepo{
		logger: logger,
		db:     db,
	}
}

func (repo *UserRepo) Add(user domain.User) error {
	userDB := database.User{}
	userDB.FromDomain(&user)

	query := repo.db.Model(&database.User{})
	err := query.Create(&userDB).Error
	if err != nil {
		repo.logger.Error("内部错误: ", err)
		return err
	}
	return nil
}

func (repo *UserRepo) Get(id, userName string) (*domain.User, error) {
	var userDB database.User
	query := repo.db.Model(&database.User{})
	if len(id) > 0 {
		query = query.Where("id = ?", id)
	}
	if len(userName) > 0 {
		query = query.Where("user_name = ?", userName)
	}
	err := query.First(&userDB).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		repo.logger.Error("内部错误: ", err)
		return nil, err
	}
	return userDB.ToDomain(), nil
}

func (repo *UserRepo) Update(user domain.User) error {
	userDB := database.User{}
	userDB.FromDomain(&user)

	query := repo.db.Model(&database.User{})
	err := query.Where("id = ?", user.ID).Updates(&userDB).Error
	if err != nil {
		repo.logger.Error("内部错误: ", err)
		return err
	}
	return nil
}

func (repo *UserRepo) Delete(id string) error {
	query := repo.db.Model(&database.User{})
	err := query.Where("id = ?", id).Delete(&database.User{}).Error
	if err != nil {
		repo.logger.Error("内部错误: ", err)
		return err
	}
	return nil
}

func (repo *UserRepo) List(listQuery domain.UserListQuery) ([]domain.User, int64, error) {
	var users []database.User
	var total int64

	// 校验分页参数
	if listQuery.Page < 1 {
		listQuery.Page = 1
	}
	if listQuery.Size < 1 {
		listQuery.Size = 10 // 默认每页大小
	}

	query := repo.db.Model(&database.User{})
	if listQuery.UserID != "" {
		query = query.Where("id = ?", listQuery.UserID)
	}
	if listQuery.UserName != "" {
		query = query.Where("user_name = ?", listQuery.UserName)
	}

	// 计算偏移量
	offset := (listQuery.Page - 1) * listQuery.Size

	// 先计算总数
	countQuery := query
	err := countQuery.Count(&total).Error
	if err != nil {
		repo.logger.Error("查询用户总数失败: ", err, " query: ", listQuery)
		return nil, 0, err
	}

	// 查询分页数据
	err = query.Offset(offset).Limit(listQuery.Size).Find(&users).Error
	if err != nil {
		repo.logger.Error("查询用户列表失败: ", err, " query: ", listQuery)
		return nil, 0, err
	}

	// 转换为 domain.User
	domainUsers := make([]domain.User, len(users))
	for i, user := range users {
		domainUsers[i] = *user.ToDomain()
	}

	return domainUsers, total, nil
}
